# @Author: 唐奇才
# @Time: 2021/5/26 19:46
# @File: my-kmeans.py
# @Software: PyCharm


from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import matplotlib.image as imgplt
import numpy as np
from sklearn.metrics import normalized_mutual_info_score,adjusted_rand_score
import os
import pandas as pd
from scipy.optimize import linear_sum_assignment as linear_assignment
import cv2
import shutil

def cluster_acc(y_true, y_pred):
    y_true = np.array(y_true).astype(np.int64)
    assert y_pred.size == y_true.size
    D = max(y_pred.max(), y_true.max()) + 1
    w = np.zeros((D, D), dtype=np.int64)
    for i in range(y_pred.size):
        w[y_pred[i], y_true[i]] += 1
    ind = linear_assignment(w.max() - w)
    i += 1
    qq = sum([w[i, j] for i, j in ind])
    return qq * 1.0 / y_pred.size

def getinfo():
    # 获取文件并构成向量
    #预测值为1维，把一张图片的三维压成1维，那么n张图片就是二维
    global total_photo, photo_name
    file = os.listdir(r'test/')
    i = 0
    for subfile in file:
        photo_name.append(r'test/' + subfile)
        target.append(i)
        i += 1
    #del(photo_name[-1])
    for path in photo_name:
        photo = imgplt.imread(path)
        hog = cv2.HOGDescriptor((80, 160), (64, 64), (8, 8), (32, 32), 9)  # winSize = (80,160), blockSize = (64,64), blockStride = (8,8), cellSize = (32,32), nbins = 9
        photo = hog.compute(photo, (8, 8), (8, 8)).reshape((1,-1))  # winStride = (8,8), padding = (8,8)
        #photo = photo.reshape(1, -1)
        photo = pd.DataFrame(photo)
        total_photo = total_photo.append(photo, ignore_index=True)
    total_photo = total_photo.values

def kmeans():
    clf = KMeans(n_clusters=16)
    clf.fit(total_photo)
    y_predict = clf.predict(total_photo)
    centers = clf.cluster_centers_
    result = centers[y_predict]
    result = result.astype("float64")
    result = result.reshape(559, 12636, 1)       #图像的矩阵大小为559张样本，分辨率为：80,160,3
    return result,y_predict

def draw():
    shutil.rmtree(r'result/')
    for i in range(0,16):
        os.makedirs('result/' + str(i) + '/')  # 创建目录
    conti = 0
    for path in photo_name:
        shutil.copy(path, r'result/' + str(y_predict[conti]))
        conti += 1

def score():
    #del (target[-1])
    #ACC = cluster_acc(target, y_predict)  # y 真实值 y_predict 预测值
    NMI = normalized_mutual_info_score(target, y_predict)
    ARI = adjusted_rand_score(target, y_predict)
    #print(" ACC = ", ACC)
    print(" NMI = ", NMI)
    print(" ARI = ", ARI)

if __name__ == '__main__':
    photo_name = []
    target = []
    total_photo = pd.DataFrame()
    getinfo()
    result,y_predict = kmeans()
    score()
    draw()

